package duoxiancheng;

/**
 * 线程安全：在并发时保证数据的正确性，效率尽可能的高
 * synchronized
 * 1.同步方法
 * 2.同步块
 */
public class synTest04 {
    public static void main(String[] args) {
        //一份资源
        syn12306 w06= new syn12306();
        //多个代理
        new Thread(w06,"问问").start();
        new Thread(w06,"大幅度").start();
        new Thread(w06,"天天").start();
    }
}

class syn12306 implements Runnable{
    private int ticket = 10;
    private Boolean flag =true;

    @Override
    public void run() {
        while (flag){
            test05();
        }
    }

    ////同步块
    public void test(){//锁的是对象,也就是w06，线程是安全的,但是范围太大，效率低
        synchronized (this){
            if (ticket<=0){
                flag=false;
                return;
            }
            try {//模拟网络延迟，高并发
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println( Thread.currentThread().getName()+"---->"+ticket--);
        }
    }

    public void test01(){//锁的是对象下的属性ticket，然而创建了多了对象，锁其中一个的tickey是锁不住的
        synchronized ((Integer)ticket){
            if (ticket<=0){
                flag=false;
                return;
            }
            try {//模拟网络延迟，高并发
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println( Thread.currentThread().getName()+"---->"+ticket--);
        }
    }

    public void test04(){//线程不安全，锁不住.三个同时进来，在出synchronized的时候ticket还是没有修改的，会出错
        synchronized (this){
            if (ticket<=0){
                flag=false;
                return;
            }
        }
        try {//模拟网络延迟，高并发
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println( Thread.currentThread().getName()+"---->"+ticket--);
    }

    public void test05(){//尽可能锁定合理的范围
        if (ticket<=0){//没票的情况
            flag=false;
            return;
        }
        synchronized (this){
            if (ticket<=0){//考虑最后一张票的情况
                flag=false;
                return;
            }
            try {//模拟网络延迟，高并发
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println( Thread.currentThread().getName()+"---->"+ticket--);
        }

    }
}